import serial
import threading
import time
from signal_buffer import SignalBuffer


class ConnSerial:
    def __init__(self, port, baud_rate, byte_size, parity, stop_bits, xon_xoff, signal_buffer):
        self.port = port
        self.baud_rate = baud_rate
        self.byte_size = byte_size
        self.parity = parity
        self.stop_bits = stop_bits
        self.xon_xoff = xon_xoff
        self.signal_buffer = signal_buffer
        self.serial = None
        self.read_thread = None
        self.running = False
        # self.is_open = False

        self.connect()

    def connect(self):
        try:
            self.serial = serial.Serial(
                port=self.port,
                baudrate=self.baud_rate,
                bytesize=self.byte_size,
                parity=self.parity,
                stopbits=self.stop_bits,
                xonxoff=self.xon_xoff,
                timeout=1
            )
            self.running = True
            self.read_thread = threading.Thread(target=self.read_from_serial)
            self.read_thread.start()
            print("串口已连接")
        except serial.SerialException as e:
            print(f"连接串口失败: {e}")
            raise

    def read_from_serial(self):
        while self.running:
            try:
                if self.serial.in_waiting > 0:
                    data = self.serial.read(self.serial.in_waiting)
                    self.signal_buffer.put(data)
                time.sleep(0.1)
            except serial.SerialException as e:
                print(f"读取串口数据时出错: {e}")
                self.close()  # 确保在发生错误时关闭串口
                break

    def close(self):
        self.running = False
        if self.read_thread is not None:
            self.read_thread.join()
        if self.serial is not None and self.serial.is_open:
            self.serial.close()
            print("串口已关闭")

    # @property 可以让方法可以像属性一样调用 比如使用该装饰器前调用is_open() 使用后直接is_open
    @property
    def is_open(self):
        # print(self.serial)
        return self.serial is not None and self.serial.is_open
